home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 12 / Cream of the Crop 12 (Part II) / Cream of the Crop 12 (Part II).iso / OS2 / BLT2_205.ZIP / src / blt2cx04.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-02-25  |  11.4 KB  |  429 lines

  1. /* 
  2.  *
  3.  * blt2cx04.c - 17-Oct-1995 Cornel Huth 
  4.  * This module is called by blt2demo.c
  5.  * UPDATE_XB
  6.  *
  7.  */
  8.  
  9. #include "platform.h"
  10.  
  11. #ifdef ON_OS2
  12.    #include <os2.h>
  13. #endif
  14. #ifdef ON_W95
  15.    #define WIN32_LEAN_AND_MEAN
  16.    #include <windows.h>
  17. #endif
  18.  
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <time.h>
  22. #include <string.h>
  23.  
  24. #ifdef ON_OS2
  25.    #include "bullet2.h"
  26. #endif
  27. #ifdef ON_W95
  28.    #include "bullet95.h"
  29. #endif
  30. #ifdef ON_DOSX
  31.    #include "bulletx.h"
  32. #endif
  33.  
  34. void cx04BuildFieldList(FIELDDESCTYPE fieldList[]);
  35.  
  36. extern CHAR *collateTable;
  37.  
  38.  
  39. int cx04() {
  40.  
  41. #pragma pack(1)
  42.  
  43. ACCESSPACK AP;
  44. DOSFILEPACK DFP;
  45. CREATEDATAPACK CDP;
  46. CREATEINDEXPACK CIP;
  47. HANDLEPACK HP;
  48. OPENPACK OP;
  49.  
  50. struct EmpRecType {
  51.  CHAR tag;              // record tag, init to SPACE, * means deleted
  52.  CHAR empID[9];         // SSN (not 0T string)
  53.  CHAR empLN[16];        // last name
  54.  CHAR empFN[16];        // first name
  55.  CHAR empHire[8];       // "YYYYMMDD" (not 0T string)
  56.  CHAR empDept[6];       // department assigned
  57. }; // 56 bytes
  58. struct EmpRecType EmpRec;
  59.  
  60. #pragma pack()
  61.  
  62. time_t startTime, endTime;
  63. int display = 0;                // display results or not flag
  64. int sameSequence = 1;           // use same random seed each time
  65. int rndSeqVar = 0;              // random "key" generated (9 digits worth)
  66. int doOptimize = 1;             // optimize index prior update and key access
  67. LONG rez;                       // return value from Bullet
  68.  
  69. CHAR nameIX3[] = "$CX04.IX3";   // name of index file created
  70. ULONG indexID=0;                // handle of index file
  71. CHAR keyExpression[128];        // key expression string buffer (159 max)
  72. CHAR keyBuffer[68];             // buffer used to store/receive key values
  73.  
  74. CHAR nameData[] = "$CX04.DBF";  // name of data file created
  75. ULONG dataID=0;                 // handle of data file
  76. FIELDDESCTYPE fieldList[5];     // 5 fields used in data record
  77.  
  78. LONG recs2add;          // records to add
  79. LONG i;                 // counter
  80. LONG recNo;             // counter
  81. CHAR tmpStr[64];        // misc stuff, non-Bullet related
  82.  
  83. printf("UPDATE_XB, an all-or-nothing transaction UPDATE into up to\n");
  84. printf("512 files (combination of data and index) from a single call.\n\n");
  85.  
  86. // Implicit is the tag field at the first byte, then comes...
  87.  
  88. memset(fieldList,0,sizeof(fieldList));  // init unused bytes to 0 (required)
  89. cx04BuildFieldList(fieldList);
  90.  
  91. // Delete previous files from any previous run (disregard any error return)
  92.  
  93. DFP.func = DELETE_FILE_DOS;
  94. DFP.filenamePtr = nameData;
  95. rez = BULLET(&DFP);
  96. DFP.filenamePtr = nameIX3;
  97. rez = BULLET(&DFP);
  98.  
  99. // Create the data file, a standard DBF (ID=3) as defined in fieldList above.
  100.  
  101. CDP.func = CREATE_DATA_XB;
  102. CDP.filenamePtr = nameData;
  103. CDP.noFields = 5;
  104. CDP.fieldListPtr = fieldList;
  105. CDP.fileID = 0x03;
  106. rez = BULLET(&CDP);
  107. if (rez) {
  108.    printf("Failed data file create.  Err: %li\n",rez);
  109.    goto Abend;
  110. }
  111.  
  112. // Open the data file (required before creating an index file for it)
  113.  
  114. OP.func = OPEN_DATA_XB;
  115. OP.filenamePtr = nameData;
  116. OP.asMode = READWRITE | DENYNONE;
  117. rez = BULLET(&OP);
  118. if (rez) {
  119.    printf("Failed data file open.  Err: %li\n",rez);
  120.    goto Abend;
  121. }
  122. dataID = OP.handle;
  123.  
  124. // Create an index file for the data file opened above.
  125.  
  126. strcpy(keyExpression,"SSN");
  127.  
  128. CIP.func = CREATE_INDEX_XB;
  129. CIP.filenamePtr = nameIX3;
  130. CIP.keyExpPtr = keyExpression;
  131. CIP.xbLink = dataID;            // the handle of the data file
  132. CIP.sortFunction = ASCII_SORT;  // sort by ASCII order (fine for text numbers)
  133. CIP.codePage = CODEPAGE;        // use OS-default code page
  134. CIP.countryCode = CTRYCODE;     // use OS-default country code
  135. CIP.collatePtr = NULL;          // since ASCII_SORT, no collate table
  136. CIP.nodeSize = 512;             // 512-byte node size (or 1024, 2048 bytes)
  137. rez = BULLET(&CIP);
  138. if (rez) {
  139.    printf("Failed index file create.  Err: %li\n",rez);
  140.    goto Abend;
  141. }
  142.  
  143. // Open the index file (what we just created above).
  144.  
  145. OP.func = OPEN_INDEX_XB;
  146. OP.filenamePtr = nameIX3;
  147. OP.asMode = READWRITE | DENYNONE;
  148. OP.xbLink = dataID;
  149. rez = BULLET(&OP);
  150. if (rez) {
  151.    printf("Failed index file open.  Err: %li\n",rez);
  152.    goto Abend;
  153. }
  154. indexID = OP.handle;
  155.  
  156. printf("Display all data accessed (slower results)? (y/N) ");
  157. gets(tmpStr);
  158. if (*tmpStr=='y') display = 1;
  159.  
  160. printf("           Repeat same random key sequence? (Y/n) ");
  161. gets(tmpStr);
  162. if (*tmpStr=='n') sameSequence = 0;
  163.  
  164. printf("               Optimize index after update? (Y/n) ");
  165. gets(tmpStr);
  166. if (*tmpStr=='n') doOptimize = 0;
  167.  
  168. printf("  How many records do you want for this test run? ");
  169. gets(tmpStr);
  170. recs2add = atol(tmpStr);
  171. if (recs2add < 1) recs2add = 1;  // would you rather end the test?
  172. if (recs2add > 9999999) recs2add = 1; // why wait around for 10M?  
  173.  
  174. // Add the data records, which are created here, on-the-fly, varying enough
  175. // to make unique records.  The key is inserted for each record added.
  176.  
  177. EmpRec.tag = ' ';                       // set to not-deleted
  178. strncpy(EmpRec.empID,"000000000",9);    // the key.field
  179. strcpy(EmpRec.empLN,"YourLastName");  ; // everyone has the same last name
  180. strcpy(EmpRec.empFN,"YourFirstName");   // everyone has this first name!
  181. strncpy(EmpRec.empHire,"19950618",8);   // YYYYMMDD DBF form, no \0 on date
  182. strcpy(EmpRec.empDept,"MIS");           // everyone works for MIS!
  183.  
  184. // The record construction creates a pretty random SSN number (.empID)
  185. // and that is used as the key -- the key is kept unique (i.e., duplicate
  186. // .empID values are not allowed).  In case of a duplicate (likely given
  187. // the SSN generation technque), the changes made to the database are
  188. // backed out by BULLET.  Another insert is made to cover the count requested.
  189.  
  190. if (sameSequence)
  191.    srand(1);
  192. else
  193.    srand((unsigned)time(0));
  194.  
  195. printf("Inserting %ld recs/keys..  ",recs2add);
  196. time(&startTime);
  197.  
  198. AP.func = INSERT_XB;
  199. AP.handle = indexID;
  200. AP.keyPtr = keyBuffer;
  201. AP.recPtr = &EmpRec;
  202. AP.nextPtr = NULL;
  203.  
  204. for (i = 1; i <= recs2add; i++) {
  205.  
  206.    rndSeqVar = (rand() >> 1) * (rand() >> 2);   // 16383*8191=134193153 max
  207.    sprintf(tmpStr,"%9.9i",rndSeqVar);
  208.    strncpy(EmpRec.empID,tmpStr,9);              // update SSN
  209.  
  210.    AP.recNo = 0;
  211.  
  212.    rez = BULLET(&AP);
  213.    if (rez) {
  214.  
  215.       // negative rc means failed during data record add
  216.  
  217.       if (rez < 0) {
  218.          rez = AP.stat;
  219.          printf("Failed during data portion, sequence %ld.  Err: %li\n",i,rez);
  220.          goto Abend;
  221.       }
  222.  
  223.       // otherwise during index key insert
  224.  
  225.       else {
  226.          rez = AP.stat;
  227.          if (rez == EXB_KEY_EXISTS) {
  228.             rez = 0;
  229.             i--;
  230.          }
  231.          else {
  232.             printf("Failed during index portion, sequence %ld.  Err: %li\n",i,rez);
  233.             goto Abend;
  234.          }
  235.       }
  236.    }
  237. }
  238. time(&endTime);
  239. printf("took %lu secs.\n",(endTime - startTime));
  240.  
  241. printf("\nUpdating the entire database by adding 200000000 to key field\n");
  242. printf(" Updating %ld recs/keys..  ",recs2add);
  243. time(&startTime);
  244.  
  245. recNo=1;
  246. AP.func = GET_RECORD_XB;        // direct access, see above notes
  247. AP.handle = dataID;             // GET_RECORD_XB uses only the data file
  248. AP.recNo = recNo;               // get the first record to start
  249. AP.keyPtr = keyBuffer;          // ...to be used by UPDATE_XB
  250. AP.recPtr = &EmpRec;
  251. AP.nextPtr = NULL;
  252. rez = BULLET(&AP);
  253. i=0;
  254.  
  255. while (rez==0) {
  256.  
  257.    // got the data record, force a key update by changing key field
  258.    // all this does is change the first digit of the nine, same effect
  259.    // as adding 200000000
  260.  
  261.    *(EmpRec.empID)+=2;
  262.  
  263.    AP.func = UPDATE_XB;
  264.    AP.handle = indexID;
  265.    rez = BULLET(&AP);  
  266.    if (rez) {
  267.       if (rez < 0) {
  268.          rez = AP.stat;
  269.          printf("Failed data update, rec#: %ld. Err: %li\n",AP.recNo,rez);
  270.          goto Abend;
  271.       }
  272.  
  273.       // otherwise during index key update
  274.  
  275.       else {
  276.          rez = AP.stat;
  277.          printf("Failed index update, rec#: %ld. Err: %li\n",AP.recNo,rez);
  278.          goto Abend;
  279.       }
  280.    }
  281.    i++;
  282.  
  283.    // change for GET_RECORD_XB...
  284.  
  285.    AP.func = GET_RECORD_XB;
  286.    AP.handle = dataID;
  287.    AP.recNo=++recNo;
  288.    rez = BULLET(&AP);
  289. }
  290. time(&endTime);
  291.  
  292. // expect error is EXB_BAD_RECNO 
  293.  
  294. if (rez==EXB_BAD_RECNO) {
  295.    printf("took %lu secs. for %ld updates\n",(endTime - startTime),i);
  296.    rez=0;
  297. }
  298. else {
  299.    printf("Failed GET_RECORD_XB at %ld.  Err: %li\n",AP.recNo,rez);
  300.    goto Abend;
  301. }
  302.  
  303. // all records now are > 200000000, as are their keys
  304.  
  305. if (doOptimize) {
  306.    printf("Optimizing index... ");
  307.    AP.func = REINDEX_XB;        // this is all there is to reindexing even...
  308.    AP.handle = indexID;         // ...million-record databases
  309.    AP.keyPtr = keyBuffer;       // if dup key error...(see manual for details)
  310.    AP.nextPtr = NULL;           // just this one index file
  311.    rez = BULLET(&AP);
  312.    if (rez)  {
  313.       rez = AP.stat;
  314.       printf("Failed optimize (reindex).  Err: %li\n",rez);
  315.       goto Abend;
  316.    }
  317.    printf("Done\n");
  318. }
  319.  
  320. memset(keyBuffer,0,sizeof(keyBuffer));
  321.  
  322. printf(" Accessing %ld keys...     ",recs2add);
  323. if (display) printf("\n");
  324. time(&startTime);
  325. AP.func = FIRST_KEY_XB;
  326. AP.handle = indexID;
  327. AP.keyPtr = keyBuffer;
  328. rez = BULLET(&AP);
  329. i=0;
  330. while (rez==0) {
  331.    i++;
  332.    if (display) printf("%s  %9.9lu\r", keyBuffer, AP.recNo);
  333.    AP.func = NEXT_KEY_XB;
  334.    rez = BULLET(&AP);
  335. };
  336. if (display) printf("\n...");
  337.  
  338. // expected rez is ERR_END_OF_FILE
  339.  
  340. if (rez!=EXB_END_OF_FILE)  {
  341.    printf("Failed KEY access.  Err: %li\n",rez);
  342.    goto Abend;
  343. }
  344. time(&endTime);
  345. printf("took %lu secs. for %ld keys\n",(endTime - startTime),i);
  346.  
  347. printf(" Accessing %ld keys+recs...",recs2add);
  348. if (display) printf("\n");
  349. time(&startTime);
  350. AP.func = GET_FIRST_XB;
  351. AP.handle = indexID;
  352. AP.keyPtr = keyBuffer;
  353. AP.recPtr = &EmpRec;
  354. rez = BULLET(&AP);
  355. i=0;
  356. while (rez==0) {
  357.    i++;
  358.    if (display) 
  359.       printf("%s  %9.9lu   %s\r", keyBuffer, AP.recNo, &EmpRec);
  360.    AP.func = GET_NEXT_XB;
  361.    rez = BULLET(&AP);
  362. }
  363. if (display) printf("\n...");
  364.  
  365. // expected rez is ERR_END_OF_FILE
  366.  
  367. if (rez!=EXB_END_OF_FILE) {
  368.    printf("Failed GET access.  Err: %li\n",rez);
  369.    goto Abend;
  370. }
  371. time(&endTime);
  372. printf("took %lu secs. for %ld keys & records\n",(endTime - startTime),i);
  373.  
  374. // Fatal errors above come straight to here
  375. Abend:
  376.  
  377. // Close files
  378.  
  379. if (indexID) {
  380.    HP.func = CLOSE_INDEX_XB;
  381.    HP.handle = indexID;
  382.    rez = BULLET(&HP);
  383.    if (rez)
  384.       printf("Failed index file close.  Err: %li\n",rez);
  385. }
  386.  
  387. if (dataID) {
  388.    HP.func = CLOSE_DATA_XB;
  389.    HP.handle = dataID;
  390.    rez = BULLET(&HP);
  391.    if (rez)
  392.       printf("Failed data file close.  Err: %li\n",rez);
  393. }
  394.  
  395. return rez;
  396. }
  397.  
  398.  
  399. //------------------------------------
  400. // Init field list items for data file
  401.  
  402. void cx04BuildFieldList(FIELDDESCTYPE fieldList[]) {
  403.  
  404. strcpy(fieldList[0].fieldName, "SSN");
  405. fieldList[0].fieldType = 'C';
  406. fieldList[0].fieldLen = 9;
  407. fieldList[0].fieldDC = 0;
  408.  
  409. strcpy(fieldList[1].fieldName, "LNAME");
  410. fieldList[1].fieldType = 'C';
  411. fieldList[1].fieldLen = 16;
  412. fieldList[1].fieldDC = 0;
  413.  
  414. strcpy(fieldList[2].fieldName, "FNAME");
  415. fieldList[2].fieldType = 'C';
  416. fieldList[2].fieldLen = 16;
  417. fieldList[2].fieldDC = 0;
  418.  
  419. strcpy(fieldList[3].fieldName, "HIRED");
  420. fieldList[3].fieldType = 'D';
  421. fieldList[3].fieldLen = 8;      // date field type must be 8.0
  422. fieldList[3].fieldDC = 0;
  423.  
  424. strcpy(fieldList[4].fieldName, "DEPT");
  425. fieldList[4].fieldType = 'C';
  426. fieldList[4].fieldLen = 6;
  427. fieldList[4].fieldDC = 0;
  428. }
  429.